iT邦幫忙

2023 iThome 鐵人賽

DAY 13
0
自我挑戰組

重新複習JavaScript系列 第 13

[Day -13] Call by value & Call by reference

  • 分享至 

  • xImage
  •  

既然都是要寫JavaScript的資訊,不免俗的要來 水一篇 好好探討一下傳值還是傳址。

我們都知道我們的資料都是被存放在記憶體裡面的,但這時候我就很好奇為什麼JS 引擎是如何為我們保留記憶體位置的?

在進入by value 和 by reference 的觀念前我們先來看一段簡單的程式:

var a = 3;
var b;

b = a;
a = 2;
console.log("a is " + a);
console.log("b is " + b)

答案會是:

a is 2
b is 3

感覺很直觀,一點都不難啊,不要急我們再往下走:

var c = {greet : "Hello!"};
var d;
d = c;

c.greet = "你好";

console.log(c);
console.log(d);

這個時候結果會變成:

Object {greet : "你好"}
Object {greet : "你好"}

疑?為什麼這裡兩個都會變成剛剛更改的?明明第一個案例a不會引響b,但為什麼第二個案例c會引響d呢?

這就是接下來我們要說明的地方。

Call By Value

當我今天創建的變數a的值是 primitive type 時,a會在記憶體中有自己的位置(0x001),當這時我打上b = a時,b會先有一個自己的記憶體位置(0x002),然後在把a的值放在自己的記憶體裡面。

因此a 和 b 雖然值一樣,但他們存在於兩個不同的記憶體位置,因此並不會乎相干擾影響。

這種情況,我們就稱為 Call By Value,而這種情形會發生在 primitive type 的變數。

Call By Reference

當我今天創建的變數a的值是object時,a一樣會在記憶體中有自己的位置(0x001),當這時我打上b = a時,b就會跟之前不一樣,b不會創建一個新的記憶體位置而是指向a的記憶體位置。

因此當 a 的值改變的時候 b 的值也會改變,因為它們實際上是指稱到相同的位置。

這種情形我們就稱為 Call By Reference,這樣情況會發生在 Object 和 Function 這種變數

一般來說,Primitive type 是 by value,而 Object 和 Function 則是 by reference,但如果只是這樣Call by value & Call by reference就不會引起這麼大的討論跟困惑。

例外情況

今天如果我們是使用 object literal 的方式指定物件的值,就不是by reference 而是會變成 by Value,如下面範例:

var a = { number: 1 };
var b;
b = a;
console.log(a);
console.log(b);

a = { number: 2 };
console.log(a);
console.log(b);

結果如下:

{ number: 1 }
{ number: 1 }
{ number: 2 }
{ number: 1 }

在這裡,如果我們是用 object literal 的方式去定義 a這個變數,在這種情況底下,因為它並不清楚 a 的內容是已經存在的,所以它會建立一個新的記憶體位置來存放 c 物件裡面的內容。

JavaScript是哪一類型?

看完上面的案例後,是不是滿腦困惑,所以既不是 call by value 也不是 call by reference,那這樣應該叫做什麼呢?

看了很多資料,看到一個名詞:call by sharing。

sharing有「共享」的意思,對於Primitive type來說,看起來會很像 by value,對於object來說則會很像 by reference。這也是目前大多數人的結論。

但與其在爭論by value 還是 by reference又或者是 by sharin,我更喜歡huli的結論是:與其由定義來看,不如直接從行為來加以區分,不同種類能夠達成的行為都不一樣。

  • 第一個條件用來區分到底是 by value 還是 by reference:「在函式裡對引數重新賦值,外面變數是否會改變?」
  • 第二個條件來區分這個 by value 是真by value 還是一個叫做 by sharing 的分支:「能否透過引數,改變外部變數的值」(我們這邊所指的「值」跟地址或引用無關,純粹在講像{numer:1}這樣子的值)

有興趣的朋友可以點進下方的參考資料看原作者的文章

參考資料:

https://blog.techbridge.cc/2018/06/23/javascript-call-by-value-or-reference/


上一篇
[Day -12] 強制轉型(Coercion)
下一篇
[Day -14] 認識DOM
系列文
重新複習JavaScript30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言